<template>
  <div class="vx-menu-tree">
    <div class="menu-tree">
      <div class="line"></div>
      <div class="menu-tree-list">
        <div class="menu-tree-item">
          <ui-tree
            ref="theTree1"
            empty-text="暂无数据"
            :default-checked-keys="defaultChecked"
            :default-expanded-keys="defaultExpanded"
            :show-checkbox="showCheckBox"
            :node-key="nodeKey"
            :data="tempArr1"
            :props="defaultProps"
          ></ui-tree>
        </div>
        <div class="menu-tree-item">
          <ui-tree
            ref="theTree2"
            empty-text="暂无数据"
            :default-checked-keys="defaultChecked"
            :default-expanded-keys="defaultExpanded"
            :show-checkbox="showCheckBox"
            :node-key="nodeKey"
            :data="tempArr2"
            :props="defaultProps"
          ></ui-tree>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'vx-menu-tree',
  data() {
    return {
      tempArr1: [],
      tempArr2: [],
      delMenuList: [],
    };
  },
  props: {
    // tree数组
    list: {
      type: Array,
      required: true,
    },
    // 是否展示复选框
    showCheckBox: {
      type: Boolean,
      default: false,
    },
    // nodeKey
    nodeKey: {
      type: String,
      default: 'Id',
    },
    defaultProps: {
      type: Object,
      default: () => {
        return {
          children: 'children',
          label: 'title',
        };
      },
    },
    // 默认展开
    defaultExpanded: {
      type: Array,
      default: () => {
        return [];
      },
    },
    // 默认选中
    defaultChecked: {
      type: Array,
      default: () => {
        return [];
      },
    },
  },
  mounted() {
    let temp = Math.ceil(this.list.length / 2);
    this.tempArr1 = this.list.slice(0, temp);
    this.tempArr2 = this.list.slice(temp);
  },
  methods: {
    /**
     * 若节点可被选择（即 show-checkbox 为 true），则返回目前被选中的节点的 key 所组成的数组
     * (leafOnly) 接收一个 boolean 类型的参数，若为 true 则仅返回被选中的叶子节点的 keys
     */
    getCheckedKeys(leafOnly) {
      let checkKeyArray1 = this.$refs.theTree1.getCheckedKeys(leafOnly);
      let checkKeyArray2 = this.$refs.theTree2.getCheckedKeys(leafOnly);
      return checkKeyArray1.concat(checkKeyArray2);
    },
    /**
     * 若节点可被选择（即 show-checkbox 为 true），则返回目前被选中的节点所组成的数组
     * (leafOnly, includeHalfChecked) 接收两个 boolean 类型的参数，1. 是否只是叶子节点，默认值为 false 2. 是否包含半选节点，默认值为 false
     */
    getCheckedNodes(leafOnly, includeHalfChecked) {
      let checkKeyArray1 = this.$refs.theTree1.getCheckedNodes(leafOnly, includeHalfChecked);
      let checkKeyArray2 = this.$refs.theTree2.getCheckedNodes(leafOnly, includeHalfChecked);
      return checkKeyArray1.concat(checkKeyArray2);
    },
    /**
     * 清空选择的节点
     */
    resetChecked() {
      this.$refs.theTree1.setCheckedKeys([]);
      this.$refs.theTree2.setCheckedKeys([]);
    },
    /**
     * 具体展开或折叠方法，也可直接调用
     */
    forTreeUpd(expanded) {
      this.$nextTick(() => {
        for (let i = 0; i < this.$refs.theTree1.store._getAllNodes().length; i++) {
          this.$refs.theTree1.store._getAllNodes()[i].expanded = expanded;
        }
        for (let i = 0; i < this.$refs.theTree2.store._getAllNodes().length; i++) {
          this.$refs.theTree2.store._getAllNodes()[i].expanded = expanded;
        }
      });
    },
    /**
     * 全部展开
     */
    expandAll() {
      this.forTreeUpd(true);
    },
    /**
     * 全部折叠
     */
    collapseAll() {
      this.forTreeUpd(false);
    },
    /**
     * 获取选中的树
     */
    getCheckedTree() {
      let menuList = this.getCheckedNodes(false, true);
      if (menuList.length == 0) {
        return [];
      }
      let menuKeyList = this.getCheckedKeys(true);

      // 获取非叶子节点，全选节点
      let oprCheckedMenuList = menuList.filter((item) => !menuKeyList.includes(item.Id));
      this.getTreeList(oprCheckedMenuList, menuKeyList);
      let set = oprCheckedMenuList.map((item) => item.Id);
      this.getDelTreeList(oprCheckedMenuList, set);
      // 删除一级节点中的非叶子节点
      for (let index = 0; index < oprCheckedMenuList.length; index++) {
        const menu = oprCheckedMenuList[index];
        if (this.delMenuList.includes(menu.Id)) {
          oprCheckedMenuList.splice(index, 1);
          index--;
        }
      }
      return oprCheckedMenuList;
    },
    /**
     * 去除父节点中未选中的子节点
     */
    getTreeList(list, keysList) {
      for (let index = 0; index < list.length; index++) {
        let menu = list[index];
        if (menu.children) {
          this.getTreeList(menu.children, keysList);
        } else {
          if (!keysList.includes(menu.Id)) {
            list.splice(index, 1);
            index--;
          }
        }
        if (menu.children && menu.children.length == 0) {
          list.splice(index, 1);
          index--;
        }
      }
    },
    /**
     * 获取一级菜单中已包含的非叶子节点
     */
    getDelTreeList(list, keys) {
      for (let index = 0; index < list.length; index++) {
        let menu = list[index];
        if (menu.children) {
          let set = menu.children.map((item) => item.Id);
          let findMenu = keys.filter((item) => {
            return set.includes(item);
          });
          if (findMenu) {
            this.delMenuList = this.delMenuList.concat(findMenu);
          } else {
            this.getDelTreeList(menu.children, keys);
          }
        }
      }
    },
  },
};
</script>

<style lang="scss">
.vx-menu-tree {
  .menu-tree {
    position: relative;
    .line {
      width: 1px;
      height: 80%;
      position: absolute;
      background-color: #ebeef5;
      top: 10%;
      left: 50%;
    }
    .menu-tree-list {
      padding: 30px 0;
      .menu-tree-item {
        display: inline-block;
        width: 50%;
        vertical-align: top;
        padding-left: 50px;
        box-sizing: border-box;
        line-height: 40px;
        font-size: 16px;
        color: #333;
      }
    }
  }
}
</style>
